package com.ledi.guns.modular.ledipay.controller;

import static com.ledi.guns.core.support.HttpKit.getIp;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.alibaba.fastjson.JSON;
import com.ledi.guns.common.exception.AppCheckException;
import com.ledi.guns.common.persistence.dao.BillAlipayMapper;
import com.ledi.guns.common.persistence.dao.UserMapper;
import com.ledi.guns.common.persistence.model.BillAlipay;
import com.ledi.guns.common.persistence.model.User;
import com.ledi.guns.common.persistence.model.vo.RoutesVo;
import com.ledi.guns.core.base.controller.BaseController;
import com.ledi.guns.core.log.LogManager;
import com.ledi.guns.core.log.factory.LogTaskFactory;
import com.ledi.guns.core.shiro.AlipayAuthToken;
import com.ledi.guns.core.shiro.ShiroKit;
import com.ledi.guns.core.shiro.ShiroUser;
import com.ledi.guns.core.util.SystemConstans;
import com.ledi.guns.modular.ledipay.controller.feignClients.AlipayApi;
import com.ledi.guns.modular.ledipay.controller.feignClients.req.DistributeRed;
import com.ledi.guns.modular.ledipay.service.impl.BillDetaileServiceImpl;
import com.ledi.guns.modular.ledipay.service.impl.BillStreamServiceImpl;
import com.ledi.guns.modular.ledipay.service.impl.EduPayAliObserver;
import com.ledi.guns.modular.system.service.IRoutesService;

/**
 * 文件名称： com.ledi.guns.modular.ledipay.controller.EduPayNotifyController.java<br/>
 * 初始作者： 周登文<br/>
 * 创建日期： 2017年11月30日<br/>
 * 功能说明： 教育缴费支付结果回调接口 <br/>
 * =================================================<br/>
 * 修改记录：<br/>
 * 修改作者 日期 修改内容<br/>
 * ================================================<br/>
 * Copyright (橘子股份-幼儿事业部) 2012-2017.All rights reserved.<br/>
 */
@Controller
@RequestMapping("restApi/notify")
public class EduPayNotifyController extends BaseController {

	private final static Logger logger = LoggerFactory.getLogger(EduPayNotifyController.class);
	@Autowired
	EduPayAliObserver aliObserver;
	@Autowired
	UserMapper userMapper;
	@Autowired
	BillAlipayMapper billAlipayMapper;
	@Autowired
	BillDetaileServiceImpl billDetaileServiceImpl;
	@Autowired
	BillStreamServiceImpl streamService;
	@Autowired
	private IRoutesService iRoutesService;
	@Autowired
	private AlipayApi alipayApi;

	@RequestMapping("/alipay")
	public void aliPayNotify(HttpServletRequest request, PrintWriter out) {

		Map<String, String> params = new HashMap<String, String>();
		Map<?, ?> requestParams = request.getParameterMap();
		for (Object name2 : requestParams.keySet()) {
			String name = (String) name2;
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = i == values.length - 1 ? valueStr + values[i] : valueStr + values[i] + ",";
			}
			// 乱码解决，这段代码在出现乱码时使用。
			try {
				valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
			} catch (UnsupportedEncodingException e) {
				logger.error(e.getMessage(), e);
			}
			params.put(name, valueStr);
		}
		String reqData = getBodyString(params);
		logger.info("receive ali pay notify:" + reqData);
		String schoolPid = params.get("seller_id");
		String receiptAmount = params.get("receipt_amount");
		String trade_status = params.get("trade_status");// TRADE_FINISHED 交易完成
		// TRADE_SUCCESS
		// 支付成功
		// true（触发通知）TRADE_CLOSED
		String ali_order_no = ""; // 交易关闭 true（触发通知）
		String passback_params = params.get("passback_params");
		String unDecodepassback_params = new String(Base64.getDecoder().decode(passback_params), StandardCharsets.UTF_8);
		logger.info("unDecodepassback_params={}", unDecodepassback_params);
		String[] tempArrray = unDecodepassback_params.split("&");
		for (String tempStr : tempArrray) {
			if (tempStr != null && tempStr.indexOf("orderNo=") != -1) {
				ali_order_no = tempStr.split("=")[1];
			}
		}
		BillAlipay billAliPay = new BillAlipay();
		billAliPay.setAlipayOrderNo(ali_order_no);
		billAliPay.setSchoolPid(schoolPid);
		billAliPay.setBillStatus(SystemConstans.BILL_STATUS_SEND_SUCCESS);
		billAliPay = billAlipayMapper.selectOne(billAliPay);
		String handleRes = "fail";
		if (billAliPay != null) {
			if ("TRADE_SUCCESS".equals(trade_status)
					&& aliObserver.syncStatus(ali_order_no, EduPayAliObserver.SYNC_STATUS_PAY_SUCCESS, billAliPay.getBillDetailId())) {
				billAliPay.setBillStatus(SystemConstans.BILL_STATUS_PAY_SUCCESS);
				billAliPay.setAlipayPersonPid(params.get("buyer_id"));
				billAliPay.setPayTime(new Date());
				billAlipayMapper.updateById(billAliPay);
				billDetaileServiceImpl.updateBillStatus(billAliPay.getBillDetailId(), SystemConstans.BILL_STATUS_PAY_SUCCESS, SystemConstans.PAY_WAY_ALI, receiptAmount);
				DistributeRed distributeRed = new DistributeRed();
				distributeRed.setPayee_user_id(params.get("buyer_id"));
				alipayApi.orderDisburse(distributeRed);
				handleRes = "success";
			}
		} else {
			handleRes = "success";
		}
		streamService.billStream("异步通知", billAliPay == null ? "" : billAliPay.getBillDetailId(), SystemConstans.API_INVOKE_TYPE_RECEIVE,
				SystemConstans.PAY_WAY_ALI, reqData, handleRes);
		logger.info("handleRes=" + handleRes);
		out.write(handleRes);
		out.close();
		return;
	}

	@RequestMapping("/alipayauth")
	public void aliAuthNotify(@RequestParam("auth_code") String auth_code) {

		logger.info("receive ali auth notify:auth_code=" + auth_code);
		HttpServletResponse response = getHttpServletResponse();
		response.setHeader("Content-type", "text/html;charset=UTF-8");
		PrintWriter out;
		try {
			out = response.getWriter();
		} catch (IOException e1) {
			e1.printStackTrace();
			return;
		}
		try {
			String school_pid = aliObserver.loginAuthToken(auth_code);
			User user = new User();
			user.setAlipayPid(school_pid);
			user.setStatus(1);
			user = userMapper.selectOne(user);
			HttpServletRequest request = getHttpServletRequest();
			String baseUri = "https://" + request.getServerName();
			String toUrl = "";
			List<RoutesVo> menuList = new ArrayList<RoutesVo>();
			if (user != null) {
				Subject currentUser = ShiroKit.getSubject();
				AlipayAuthToken token = new AlipayAuthToken(user.getAccount(), user.getPassword());
				try {
					currentUser.login(token);
				} catch (IncorrectCredentialsException e) {
					throw new AppCheckException("system.user.noteixt.code", "system.user.noteixt.message");
				} catch (LockedAccountException e) {
					throw new AppCheckException("system.user.freze.code", "system.user.freze.message");
				} catch (AuthenticationException e) {
					throw new AppCheckException("system.user.noteixt.code", "system.user.noteixt.message");
				}
				ShiroUser shiroUser = ShiroKit.getUser();
				super.getSession().setAttribute("shiroUser", shiroUser);
				super.getSession().setAttribute("username", shiroUser.getAccount());
				LogManager.me().executeLog(LogTaskFactory.loginLog(shiroUser.getId(), getIp()));
				ShiroKit.getSession().setAttribute("sessionFlag", true);
				toUrl = baseUri + "/pay/#/payindex";
				menuList = iRoutesService.selectMenus(6L);
			} else {
				toUrl = baseUri + "/pay/#/login?schoolPid=" + school_pid;
			}
			String storageUser = JSON.toJSONString(ShiroKit.getUser());
			String storageMenuList = JSON.toJSONString(menuList);
			logger.info("sessionStorageUser=" + storageUser);
			StringBuffer html = new StringBuffer("");
			html.append("<script>");
			html.append("var user=JSON.stringify(").append(storageUser).append(");");
			html.append("sessionStorage.setItem(\"user\",user);");
			html.append("localStorage.setItem(\"user\",user);");
			html.append("localStorage.setItem(\"role\",6);");
			html.append("localStorage.setItem(\"userId\",").append(ShiroKit.getUser().getId()).append(");");
			html.append("var menuList=JSON.stringify(").append(storageMenuList).append(");");
			html.append("localStorage.setItem(\"menuList\",menuList);");
			html.append("window.location.href='").append(toUrl).append("';");
			html.append("</script>");
			out.write(html.toString());
		} catch (AppCheckException e) {
			out.write(e.getMessage());
			logger.error(e.getMessage(), e);
		} catch (Exception e) {
			out.write(e.getMessage());
			logger.error(e.getMessage(), e);
		}
		out.flush();
		out.close();
		return;
	}

	private String getBodyString(Map<String, String> params) {

		Set<String> keySet = params.keySet();
		StringBuilder str = new StringBuilder();
		try {
			for (String key : keySet) {
				if (str.length() > 0) {
					str.append("&");
				}
				str.append(key).append("=").append(params.get(key));
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		return str.toString();
	}
}
